/*
 * threading-win32.c
 *
 *  Created on: 2012-05-20
 *      Author: Aco
 */

#ifdef WIN32

#include "threading.h"
#include <stdlib.h>
#include <time.h>

#include <signal.h>
//#include <sched.h>
#include <windows.h>
#include <tchar.h>
#include <stdio.h>

typedef struct
{
	void * param;
	CTFPTR fptr;
} WNWrapper;

DWORD WINAPI win_native_thread_function(LPVOID lpParam)
{
	WNWrapper * wparam = (WNWrapper*)lpParam;
	wparam->fptr(wparam->param);
	free(wparam);
	return 0;
}

CUThread * cu_spawnThread(CTFPTR func, void * param)
{
	CUThread * thread = (CUThread*) malloc(sizeof(CUThread));
	HANDLE handle;
	WNWrapper * wrap = (WNWrapper*)malloc(sizeof(WNWrapper));


	DWORD t_id;
	wrap->fptr = func;
	wrap->param = param;

	handle = CreateThread(NULL, 0, win_native_thread_function, (void*)wrap, 0, &t_id);

	if(handle == NULL)
	{
		free(thread);
		free(wrap);
		return NULL;
	}
	else
	{
		thread->state = CUT_RUNNING;
		thread->win_handle = handle;
		return thread;
	}
}

int cu_joinThread(CUThread * thread)
{
	if(thread == NULL) return CU_ERROR;
	return WaitForSingleObject(thread->win_handle, INFINITE) == WAIT_FAILED ? CU_ERROR : CU_OK;
}

void cu_sleep(int ms)
{
	Sleep(ms);
}

CUMutex * cu_createMutex()
{
	CUMutex * m = (CUMutex*)calloc(1, sizeof(CUMutex));
	m->win_mutex = CreateMutex(NULL, FALSE, NULL);
	return m;
}

void cu_lockMutex(CUMutex * m)
{
	m->state = 2;
	WaitForSingleObject(m->win_mutex, INFINITE);
	m->state = 1;
}

void cu_unlockMutex(CUMutex * m)
{
	ReleaseMutex(m->win_mutex);
	m->state = 0;
}

int cu_killThread(CUThread * thread)
{
	if(thread == NULL) return CU_ERROR;
	if(TerminateThread(thread->win_handle, 0))
		return CU_OK;
	else
		return CU_ERROR;
}

#endif
